package com.thinkit.bigdata.web.controller.sercutiry;

import com.thinkit.bigdata.core.feature.orm.mybatis.Page;
import com.thinkit.bigdata.core.util.RSAUtil;
import com.thinkit.bigdata.core.util.StringUtil;
import com.thinkit.bigdata.web.controller.pubmet.SessionManage;
import com.thinkit.bigdata.web.model.config.SysArea;
import com.thinkit.bigdata.web.model.result.ConfigResult;
import com.thinkit.bigdata.web.model.result.Constants;
import com.thinkit.bigdata.web.model.result.HtmlResult;
import com.thinkit.bigdata.web.model.sec.*;
import com.thinkit.bigdata.web.model.sys.SysConfig;
import com.thinkit.bigdata.web.service.sec.PasswordCheckService;
import com.thinkit.bigdata.web.service.sec.RoleService;
import com.thinkit.bigdata.web.service.sys.SysConfigService;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.session.Session;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

/**
 * Modify by huzenghui on 2019/7/8.
 */
@Controller
@RequestMapping("users")
public class UserController extends SessionManage {

    private Logger logger = Logger.getLogger(UserController.class);

    @Resource
    private SysConfigService sysConfigService;

    @Resource
    private PasswordCheckService passwordCheckService;

    @Resource
    private RoleService roleService;

    /**
     * 请求进入用户管理页面
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/users", method = RequestMethod.GET)
    public String showUsers(HttpServletRequest request, Model model) {
        logger.info("进入用户管理页面");
        return "SercutiryViews/user";
    }

    /**
     * 获取某省份下所有用户（id、姓名）信息
     * 集团人员获取所有用户 省份人员获取其所在省用户
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/showAllUsers", method = RequestMethod.GET)
    public List<Map<String, Object>> selectUsersByProvince() {
        List<User> userList = new ArrayList<>();
        // 获取当前登录用户所属省份信息
        SysArea area = (SysArea) SecurityUtils.getSubject().getSession().getAttribute("areaInfo");
        if (area != null) {
            // 如果省份信息不为空 则查询该省份下所有用户
            Long areaId = Long.valueOf(area.getId());
            userList = userService.selectUserByAreaId(areaId);
        } else {
            // 否则查询所有用户信息
            UserExample example = new UserExample();
            example.setOrderByClause("id asc");
            userList = userService.selectByExample(example);
        }
        // 对查询结果进行处理 去除不需要的信息 只返回id userName
        List<Map<String, Object>> result = new ArrayList<>();
        for (User user : userList) {
            Map<String, Object> tmp = new HashMap<>();
            tmp.put("id", user.getId());
            tmp.put("userName", user.getUsername());
            result.add(tmp);
        }
        return result;
    }

    /**
     * 分页查询用户信息
     *
     * @param request
     * @param sortOrder 排序方式
     * @param sortName  排序列名
     * @param pageNum   页码
     * @param pageSize  每页显示数量
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/usersByPage", method = RequestMethod.POST)
    public Page<User> usersByPage(
            HttpServletRequest request,
            @RequestParam(value = "sortOrder") String sortOrder,
            @RequestParam(value = "sortName") String sortName,
            @RequestParam(value = "isDelete", required = false) List<Integer> isDelete,
            @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) {
        // 查询参数
        String areaId = request.getParameter("areaId");   //省份id
        String groupId = request.getParameter("groupId");   //组织机构id
        String account = request.getParameter("account");   //工号
        String userName = request.getParameter("userName"); //用户名
        String realName = request.getParameter("realName"); //真实姓名
        String logTxt = "【用户分页查询】";
        logger.info(logTxt + "查询条件: pageNum=" + pageNum);
        logger.info(logTxt + "查询条件: pageSize=" + pageSize);
        logger.info(logTxt + "查询条件: areaId=" + areaId);
        logger.info(logTxt + "查询条件: groupId=" + groupId);
        logger.info(logTxt + "查询条件: account=" + account);
        logger.info(logTxt + "查询条件: userName=" + userName);
        logger.info(logTxt + "查询条件: realName=" + realName);
        logger.info(logTxt + "查询条件: isDelete=" + StringUtils.join(isDelete, ","));
        // 查询条件设置
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        // 限制超管和省份人员不能查询出自己进行操作 只有集团人员能查询出来自己
        User user = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        if (user.getGroupid() == null || user.getGroup().getAreaid().longValue() != Constants.GROUP_AREAID.longValue()) {
            // 如果用户所属机构为null(说明为admin) 用户所属省份id不为集团id 则限制用户不能查询出来自己
            criteria.andIdNotEqualTo(user.getId());
        }
        // 限制用户不能查询出来admin 如果groupid不为空 肯定查询不出来admin 如果为空 则设置groupid不能为空（admin没有groupid）
        if (StringUtil.isEmpty(groupId)) {
            criteria.andGroupidIsNotNull();
            // 当groupId为空 判断areaid 获取当前登录用户允许访问的组织机构范围
            List<Long> subGroupIdList = userService.getAllSubGroupId(areaId);
            if (!subGroupIdList.isEmpty()) {
                criteria.andGroupidIn(subGroupIdList);
            }
        }
        if (StringUtil.isNotEmpty(groupId) && groupId.matches("\\d*")) {
            // 根据groupId递归获取该部门下所有部门id
            List<Long> groupIdList = new ArrayList<>();
            groupIdList.add(Long.valueOf(groupId));
            recursionGroupId(Long.valueOf(groupId), groupIdList);
            criteria.andGroupidIn(groupIdList);
        }
        if (StringUtil.isNotEmpty(account)) {
            criteria.andAccountLike("%" + account + "%");
        }
        if (StringUtil.isNotEmpty(userName)) {
            criteria.andUsernameLike("%" + userName + "%");
        }
        if (StringUtil.isNotEmpty(realName)) {
            criteria.andRealnameLike("%" + realName + "%");
        }
        if (isDelete != null && !isDelete.isEmpty()) {
            criteria.andIsdeleteIn(isDelete);
        }
        // 排序方式设置
        example.setOrderByClause(sortName + " " + sortOrder);
        // 分页设置
        Page<User> page = new Page<>(pageNum, pageSize);
        userService.selectByExampleAndPage(page, example);
        List<User> result = page.getResult();
        for (User u : result) {
            // 对身份证号进行处理
            String idcard = u.getIdcard();
            if (StringUtil.isNotEmpty(idcard) && idcard.length() > 8) {
                u.setIdcard(idcard.substring(0, 8) + "**********");
            }
            // 对手机号进行处理
            String mobile = u.getMobileno();
            if (StringUtil.isNotEmpty(mobile) && mobile.length() > 8) {
                u.setMobileno(mobile.substring(0, 8) + "*****");
            }
        }
        logger.info(logTxt + "共计查询到" + result.size() + "条用户信息");
        return page;
    }

    /**
     * 递归获取某部门下所有机构id
     *
     * @param groupId
     * @param groupIdList
     */
    private void recursionGroupId(Long groupId, List<Long> groupIdList) {
        SysGroupExample groupExample = new SysGroupExample();
        groupExample.createCriteria().andParentidEqualTo(groupId);
        List<SysGroup> groupList = groupService.selectByExample(groupExample);
        for (SysGroup group : groupList) {
            groupIdList.add(group.getId());
            recursionGroupId(group.getId(), groupIdList);
        }
    }

    /**
     * 组织机构校验 集团用户允许为空 否则不允许为空
     *
     * @return
     */
    @ResponseBody
    @RequestMapping("/isGroupCanBeNull")
    public String isGroupCanBeNull() {
        SysArea area = (SysArea) SecurityUtils.getSubject().getSession().getAttribute("areaInfo");
        if (area != null) {
            return "no";
        }
        return "yes";
    }

    /**
     * 判断用户名是否重复
     *
     * @param username
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/userNameUniqueness", method = RequestMethod.GET)
    public ConfigResult userNameUniqueness(@RequestParam(value = "username") String username) {
        String logTxt = "【用户名称唯一性验证】";
        logger.info(logTxt + "username=" + username);
        UserExample userExample = new UserExample();
        userExample.createCriteria().andUsernameEqualTo(username);
        int count = userService.countByExample(userExample);
        if (count > 0) {
            logger.info(logTxt + "该用户已存在");
            return new ConfigResult(Constants.ERROR, "该工号已存在");
        } else {
            logger.info(logTxt + "该用户名可用");
            return new ConfigResult(Constants.SUCCESS, "√");
        }
    }

    /**
     * 判断工号是否重复
     *
     * @param request
     * @param account
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/accountUniqueCheck", method = POST)
    public ConfigResult accountUniqueCheck(HttpServletRequest request, @RequestParam(value = "account") String account) {
        String logTxt = "【工号唯一性验证】";
        logger.info(logTxt + "account=" + account);
        UserExample userExample = new UserExample();
        userExample.createCriteria().andAccountEqualTo(account);
        int count = userService.countByExample(userExample);
        if (count > 0) {
            logger.info(logTxt + "该工号已存在");
            return new ConfigResult(Constants.ERROR, "该工号已存在");
        } else {
            logger.info(logTxt + "该工号可用");
            return new ConfigResult(Constants.SUCCESS, "√");
        }
    }

    /**
     * 判断email是否重复
     *
     * @param request
     * @param email
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/emailUniqueCheck", method = GET)
    public ConfigResult emailUniqueCheck(HttpServletRequest request, @RequestParam(value = "email") String email) {
        String logTxt = "【email唯一性验证】";
        logger.info(logTxt + "email=" + email);
        UserExample userExample = new UserExample();
        userExample.createCriteria().andEmailEqualTo(email);
        int count = userService.countByExample(userExample);
        if (count > 0) {
            logger.info(logTxt + "该email已存在");
            return new ConfigResult(Constants.ERROR, "该email已存在");
        } else {
            logger.info(logTxt + "该email可用");
            return new ConfigResult(Constants.SUCCESS, "√");
        }
    }

    /**
     * 判断身份证号是否重复
     *
     * @param request
     * @param idcard
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/idcardUniqueCheck", method = GET)
    public ConfigResult idcardUniqueCheck(HttpServletRequest request, @RequestParam(value = "idcard") String idcard) {
        String logTxt = "【身份证号唯一性验证】";
        logger.info(logTxt + "idcard=" + idcard);
        UserExample userExample = new UserExample();
        userExample.createCriteria().andIdcardEqualTo(idcard);
        int count = userService.countByExample(userExample);
        if (count > 0) {
            logger.info(logTxt + "该身份证号已存在");
            return new ConfigResult(Constants.ERROR, "该身份证号已存在");
        } else {
            logger.info(logTxt + "该身份证号可用");
            return new ConfigResult(Constants.SUCCESS, "√");
        }
    }

    /**
     * 判断当前登录用户类型是不是质检或者坐席
     * 在修改用户时 如果登录用户时质检或坐席 则不允许他们修改用户的所属机构
     *
     * @return
     */
    @ResponseBody
    @RequestMapping("/userTypeCheck")
    public String userTypeCheck() {
        User user = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        SysGroup group = user.getGroup();
        if (group != null && group.getType() != 2) {
            // 如果机构不为空 机构类型不是部门 返回yes 代表是质检或坐席
            return "yes";
        }
        return "no";
    }

    /**
     * 新增用户
     *
     * @param request
     * @param user
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/userAdd", method = POST)
    public ConfigResult addUser(HttpServletRequest request, User user) {
        String logTxt = "【用户添加方法】";
        logger.info(logTxt + user.toString());
        // 校验用户名是否重复
        UserExample userExample = new UserExample();
        userExample.createCriteria().andUsernameEqualTo(user.getUsername());
        int count = userService.countByExample(userExample);
        if (count > 0)
            return new ConfigResult(Constants.ERROR, "该工号已存在");
        // 设置添加时间与添加人
        User loginUser = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        Date date = new Date();
        Long loginUserId = loginUser.getId();
        user.setPassword(getInitPassword());
        user.setCreatetime(date);
        user.setCreateuserid(loginUserId);
        user.setLastupdatetime(date);
        user.setLastupdateuserid(loginUserId);
        try {
            int rowNum = userService.insert(user);
            if (rowNum > 0) {
                logger.info(logTxt + "成功添加" + user.toString() + "用户信息");
                return new ConfigResult(Constants.SUCCESS, "新增用户成功");
            } else {
                logger.info(logTxt + "添加" + user.toString() + "用户信息失败");
                return new ConfigResult(Constants.FAIL, "新增用户失败");
            }
        } catch (Exception e) {
            logger.error(logTxt + "添加" + user.toString() + "用户错误", e);
            return new ConfigResult(Constants.ERROR, "添加用户错误");
        }
    }

    /**
     * 根据主键信息获取user信息 包含角色id信息
     *
     * @param request
     * @param id
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getUserByPK", method = RequestMethod.POST)
    public User getUserByPK(HttpServletRequest request, Long id) {
        logger.info("获取id为" + id + "的用户信息");
        return userService.getUserByPK(id);
    }

    /**
     * 修改用户
     *
     * @param request
     * @param user
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/userUpdate", method = POST)
    public ConfigResult updateUser(HttpServletRequest request, User user) {
        String logTxt = "【用户修改方法】";
        logger.info(logTxt + user.toString());
        // 获取当前登录用户 设置更新时间与更新人
        User loginUser = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        user.setLastupdateuserid(loginUser.getId());
        user.setLastupdatetime(new Date());
        try {
            int rowNum = userService.update(user);
            if (rowNum > 0) {
                logger.info(logTxt + "成功修改" + user.toString() + "用户信息");
                // 更新session中用户信息
                updateAllInfoInsession();
                return new ConfigResult(Constants.SUCCESS, "用户信息修改成功");
            } else {
                logger.info(logTxt + user.toString() + "用户信息修改失败");
                return new ConfigResult(Constants.FAIL, "用户信息修改失败");
            }
        } catch (Exception e) {
            logger.error(logTxt + user.toString() + "用户信息修改错误", e);
            return new ConfigResult(Constants.ERROR, "用户信息修改错误");
        }
    }

    // 不允许集团二级机构下人员操作集团人员信息 操作检查 true 允许操作 false不允许操作
    private boolean userOperationCheck(List<Long> userIdList) {
        // 获取当前登录人信息
        Session session = SecurityUtils.getSubject().getSession();
        User loginUser = (User) session.getAttribute(Constants.SESSION_USER_INFO);
        SysArea area = (SysArea) session.getAttribute("areaInfo");
        // 不允许集团二级机构下人员操作集团人员信息 先判断用户是不是集团二级机构下的人员
        // 满足条件1说明为admin或集团人员 条件2 说明为集团人员 条件3说明为集团 二级机构下的用户
        if (area == null && loginUser.getGroupid() != null && loginUser.getGroup().getParentid() != null) {
            SysGroupExample example = new SysGroupExample();
            // 查询所有集团机构id 再根据机构id查询出所有集团用户
            example.createCriteria().andAreaidEqualTo(Constants.GROUP_AREAID);
            List<SysGroup> groupList = groupService.selectByExample(example);
            if (!groupList.isEmpty()) {
                List<Long> groupIdList = new ArrayList<>();
                for (SysGroup group : groupList) {
                    groupIdList.add(group.getId());
                }
                // 判断有没有用户在上面查询出来的机构里 如果有 则不允许操作
                UserExample userExample = new UserExample();
                userExample.createCriteria().andGroupidIn(groupIdList).andIdIn(userIdList);
                List<User> userList = userService.selectByExample(userExample);
                if (!userList.isEmpty()) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 多个用户状态修改
     *
     * @param idList   批量修改的用户id
     * @param isdelete 状态
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/userStatusBatch", method = RequestMethod.POST)
    public ConfigResult userStatusBatch(@RequestParam("idList") List<Long> idList, @RequestParam("isdelete") Integer isdelete) {
        // 对集团二级机构的人员操作进行校验 不允许其操作集团人员信息
        if (!idList.isEmpty() && !userOperationCheck(idList)) {
            return new ConfigResult(Constants.WARNING, "需要集团上级用户操作");
        }
        // 设置更新时间与更新人
        User loginUser = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        // 判断操作类型
        String opType = (isdelete == 0) ? "启用" : "停用";
        String logTxt = "【用户状态-" + opType + "】";
        logger.info(logTxt + "修改id为" + StringUtils.join(idList, ",") + "的用户的状态");
        if (!idList.isEmpty()) {
            if (idList.contains(loginUser.getId())) {
                logger.info(logTxt + "要修改的账号中包含自身账号，不允许操作");
                return new ConfigResult(Constants.WARNING, "不允许修改自身账号状态");
            }
            // 设置 要更新的用户信息
            User user = new User();
            user.setIsdelete(isdelete);
            user.setErrornum(0);// 同时设置错误次数为0 可以实现冻结用户启用后还有5次机会输错
            if (isdelete == 3) {
                // 如果是停用操作 则同时设置密码为初始密码 sql里面另设置了pswSetTime为null 防止再次启用用户时登录不能实现强制修改密码
                user.setPassword(getInitPassword());
            }
            user.setLastupdateuserid(loginUser.getId());
            user.setLastupdatetime(new Date());
            UserExample example = new UserExample();
            example.createCriteria().andIdIn(idList);
            try {
                int rowNum = userService.updateByExampleSelective(user, example);
                if (rowNum > 0) {
                    logger.info(logTxt + "用户状态批量修改成功");
                    return new ConfigResult(Constants.SUCCESS, "用户状态批量修改成功");
                } else {
                    logger.info(logTxt + "用户状态批量修改失败");
                    return new ConfigResult(Constants.FAIL, "用户状态批量修改失败");
                }
            } catch (Exception e) {
                logger.error(logTxt + "用户状态批量修改错误", e);
                return new ConfigResult(Constants.ERROR, "用户状态批量修改错误");
            }
        } else {
            logger.info(logTxt + "未选中任何要修改状态的用户");
            return new ConfigResult(Constants.WARNING, "未选中任何要修改状态的用户");
        }
    }

    /**
     * 单个或批量删除用户
     *
     * @param idList
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/usersDeleteBatch", method = POST)
    public ConfigResult usersDeleteBatch(@RequestParam(value = "idList") List<Long> idList) {
        // 对集团二级机构的人员操作进行校验 不允许其操作集团人员信息
        if (!idList.isEmpty() && !userOperationCheck(idList)) {
            return new ConfigResult(Constants.WARNING, "需要集团上级用户操作");
        }
        String logTxt = "【用户删除方法】";
        logger.info(logTxt + StringUtils.join(idList, ","));
        if (!idList.isEmpty()) {
            // 判断要删除的账号有没有自己 因为集团人员可以查询出来自己了
            User user = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
            if (idList.contains(user.getId())) {
                return new ConfigResult(Constants.FAIL, "不允许删除自己");
            }
            try {
                int rowNum = userService.deleteUser(idList);
                if (rowNum > 0) {
                    logger.info(logTxt + "成功删除账号" + rowNum + "个");
                    return new ConfigResult(Constants.SUCCESS, "账号删除成功");
                } else {
                    logger.info(logTxt + "账号删除失败");
                    return new ConfigResult(Constants.FAIL, "账号删除失败");
                }
            } catch (Exception e) {
                logger.error(logTxt + "账号删除错误", e);
                return new ConfigResult(Constants.ERROR, "账号删除错误");
            }
        } else {
            logger.info("未选中任何要删除的账号");
            return new ConfigResult(Constants.WARNING, "未选中任何要删除的账号");
        }
    }

    /**
     * 初始化密码
     * 有一个隐藏操作 将密码设置时间修改为了null 下次登录时将强制用户修改密码
     *
     * @param request
     * @param id
     * @return
     */
    @ResponseBody
    @RequestMapping("/passwordInit")
    public ConfigResult passwordInit(HttpServletRequest request, @RequestParam("id") Long id) {
        String logTxt = "【密码初始化】";
        logger.info("对id为" + id + "的用户密码进行初始化");
        User user = new User();
        user.setId(id);
        // 设置初始密码
        user.setPassword(getInitPassword());
        user.setLastupdatetime(new Date());
        user.setLastupdateuserid(user.getId());
        // 重置密码错误次数为0
        user.setErrornum(0);
        try {
            int rowNum = userService.updateInitPasswordByPrimaryKey(user);
            if (rowNum > 0) {
                logger.info(logTxt + "成功初始化用户" + id + "的密码");
                return new ConfigResult(Constants.SUCCESS, "密码初始化成功");
            } else {
                logger.info(logTxt + id + "密码初始化失败");
                return new ConfigResult(Constants.FAIL, "密码初始化失败");
            }
        } catch (Exception e) {
            logger.error(logTxt + id + "密码初始化错误", e);
            return new ConfigResult(Constants.ERROR, "密码初始化错误");
        }
    }

    /**
     * 获取用户已设定的坐席组信息
     *
     * @param request
     * @param userId
     * @return
     */
    @ResponseBody
    @RequestMapping("/selectedSeat")
    public QcRelationDto selectedSeat(HttpServletRequest request, @RequestParam("userId") Long userId) {
        logger.info("获取用户【userId=" + userId + "】的已设定的坐席组信息");
        return userService.selectedSeat(userId);
    }

    /**
     * 质检员坐席组关系设定--未使用
     *
     * @param request
     * @param qcRelation
     * @return
     */
    @ResponseBody
    @RequestMapping("/qcRelationSave")
    public ConfigResult qcRelationSave(HttpServletRequest request, QcRelationDto qcRelation) {
        String logTxt = "【质检员坐席组关系设定】";
        logger.info(logTxt + qcRelation.toString());
        try {
            int rowNum = userService.insertQcRelation(qcRelation);
            logger.info(logTxt + "质检员坐席组关系设定成功，成功写入数据" + rowNum + "条");
            return new ConfigResult(Constants.SUCCESS, "数据访问范围设定成功");
        } catch (Exception e) {
            logger.error(logTxt + "质检员坐席组关系设定错误", e);
            return new ConfigResult(Constants.ERROR, "数据访问范围设定错误");
        }
    }

    /**
     * 个人中心-个人设置页面 用户修改密码功能
     * 注意要更新密码设置时间
     *
     * @param password
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/userUpdatePassword2", method = RequestMethod.POST)
    public HtmlResult updateUserPassword2(@RequestParam(value = "password") String password) {
        logger.info("进入用户修改 userUpdate Controller 方法");
        Session session = SecurityUtils.getSubject().getSession();
        User loginUser = (User) session.getAttribute(Constants.SESSION_USER_INFO);
        // 密码解密 因为个人页面修改密码后不刷新跳转 所以session中的privateKey此处不清楚 防止连续修改密码
        String decrypt = RSAUtil.decrypt(password, (String) session.getAttribute(RSAUtil.PRIVATE_KEY));
        if (decrypt == null) {
            // 防止session过期的时候取到null
            return HtmlResult.failure("密码修改失败");
        }
        // MD5加密
        Md5Hash hash = new Md5Hash(decrypt, "加盐", 2);//散裂2次v
        User user = new User();
        user.setId(loginUser.getId());
        user.setPassword(hash.toString());
        user.setPswsettime(new Date());
        try {
            // 个人中心修改密码 也是先校验密码 再修改密码
            return passwordCheckService.updatePassword(user);
        } catch (Exception e) {
            logger.error("用户密码出现错误", e);
        }
        return HtmlResult.failure("密码修改失败");
    }

    @ResponseBody
    @RequestMapping(value = "/passwordSale", method = POST)
    public HtmlResult passwordSale() {
        User user = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        String userName = user.getUsername();
        String password = user.getPassword();
        Long id = user.getId();
        Md5Hash hash = new Md5Hash(password, "加盐", 2);//散裂2次
        Map<String, Object> result = new HashMap<>();
        result.put("code", "");
        result.put("areaId", "");
        SysArea area = (SysArea) SecurityUtils.getSubject().getSession().getAttribute("areaInfo");
        if (area != null) {
            result.put("code", area.getCode());
            result.put("areaId", area.getId());
        }
        Integer userIdentity = (Integer) SecurityUtils.getSubject().getSession().getAttribute("userIdentity");
        result.put("userIdentity", "");
        if (userIdentity != null) {
            result.put("userIdentity", userIdentity);
        }
        result.put("id", id);
        result.put("userName", userName);
        result.put("password", hash.toString());
        return HtmlResult.success(result);
    }

    /* 未使用方法 by lihongli 2019/2/23
    @RequestMapping(value = "/userMessage", method = GET)
    public String userMessage(Model model) {
        return "SercutiryViews/userMessage";
    }*/

    /**
     * 密码比较 前端密码使用RSA加密后 此处解码并与session中MD5密码进行比较
     *
     * @param password
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/passwordCompare")
    public String passwordCompare(@RequestParam(value = "password") String password) {
        Session session = SecurityUtils.getSubject().getSession();
        // RSA解密后密码
        String decrypt = RSAUtil.decrypt(password, (String) session.getAttribute(RSAUtil.PRIVATE_KEY));
        if (decrypt == null) {
            // 防止session过期的时候取到null
            return "fault";
        }
        // md5加密
        Md5Hash hash = new Md5Hash(decrypt, "加盐", 2);//散裂2次
        // 因为要对比密码信息 防止session中信息没有更新 重新获取下
        updateUserInfo();
        User user = (User) session.getAttribute(Constants.SESSION_USER_INFO);
        if (user.getPassword().equals(hash.toString())) {
            return "success";
        }
        return "fault";
    }

    /**
     * 获取初始化密码并加密
     *
     * @return
     */
    private String getInitPassword() {
        // 获取保存密码信息的系统配置项
        SysConfig config = sysConfigService.sysConfigGetByPK(Constants.PASS_WORD_CODE);
        String password;
        if (config == null) {
            password = Constants.INIT_PASS_WORD;
        } else {
            password = config.getValue();
        }
        // 密码加密
        Md5Hash hash = new Md5Hash(password, "加盐", 2);//散裂2次
        return hash.toString();
    }

    /**
     * 判断用户是不是快到密码过期时间 了 如果是 则给出提示让用户尽快修改密码
     * （未使用--note by lihongli, 如果使用 配置项名称需要修改）
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/remindUpdatePass", method = RequestMethod.GET)
    public HtmlResult tip() {
        // 先取出当前登录用户的信息
        User user = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        UserExample example = new UserExample();
        example.createCriteria().andIdEqualTo(user.getId());
        List<User> userList = userService.selectByExample(example);
        // 取出密码多少天不修改时 开始提醒用户
        SysConfig config = sysConfigService.sysConfigGetByPK(Constants.PSW_MAX_DAY);
        int days = 60;// 给设定一个默认值 防止程序出错
        if (config != null) {
            try {
                days = Integer.valueOf(config.getValue());
            } catch (NumberFormatException e) {
                // 不做处理
            }
        }
        // 判断密码多少天没有修改了 是否要给出提醒修改密码
        if (!userList.isEmpty()) {
            // 取出密码设置时间
            Date pswsettime = userList.get(0).getPswsettime();
            if (pswsettime == null) {
                // 如果密码设置时间null的话 取用户创建时间 正常情况下不会出现这种情况
                pswsettime = userList.get(0).getCreatetime();
            }
            // 对时间进行比较 判断是否要给出提示
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(pswsettime);
            calendar.add(Calendar.DAY_OF_MONTH, days);
            if (calendar.getTime().before(new Date())) {
                // 还没到密码提醒时间
                return HtmlResult.success("未到密码提醒时间");
            } else {
                return HtmlResult.tips("密码即将过期，请尽快修改密码");
            }
        }
        // 如果没有取到信息 则提示重新登录
        return HtmlResult.failure("登录信息有误");
    }

    /**
     * 批量导入用户（旧模板）
     *
     * @param request
     * @param groupId
     * @return
     */
    @ResponseBody
    @RequestMapping("/batchImportUser")
    public ConfigResult batchImportUser(
            HttpServletRequest request,
            @RequestParam("uploadFile") MultipartFile uploadFile,
            @RequestParam("groupid") Long groupId,
            @RequestParam("roleid") Long roleId) {
        String logTxt = "【批量导入用户信息】";
        logger.info(logTxt + "所属组groupId= " + groupId + ", 角色roleId= " + roleId);
        List<Long> roleIdList = new ArrayList<>();
        roleIdList.add(roleId);
        try {
            // 读取excel文件
            HSSFWorkbook hwb = new HSSFWorkbook(uploadFile.getInputStream());
            // 读取第一个sheet表格
            HSSFSheet sheet = hwb.getSheetAt(0);
            List<User> userList = new ArrayList<>();
            User loginUser = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
            Long loginUserId = loginUser.getId();
            for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                HSSFRow row = sheet.getRow(i);
                if (row.getCell(0).getStringCellValue() == "") continue;
                User user = new User();
                user.setGroupid(groupId);
                user.setRoleidlist(roleIdList);
                user.setUsername(getStringCellValue(row.getCell(0)));
                user.setUsername(getStringCellValue(row.getCell(0)));
                user.setRealname(getStringCellValue(row.getCell(1)));
                user.setPassword(getInitPassword());
                user.setAccount(getStringCellValue(row.getCell(2)));
                user.setMobileno(getStringCellValue(row.getCell(3)));
                user.setIdcard(getStringCellValue(row.getCell(4)));
                user.setEmail(getStringCellValue(row.getCell(5)));
                // 设置作者信息
                Date date = new Date();
                user.setCreateuserid(loginUserId);
                user.setCreatetime(date);
                user.setLastupdateuserid(loginUserId);
                user.setLastupdatetime(date);
                userList.add(user);
            }
            // 批量添加用户
            int rowNum = userService.insertUsers(userList);
            int failNum = userList.size() - rowNum;
            logger.info(logTxt + "成功批量导入用户" + rowNum + "个，" + failNum + "个导入失败");
            if (rowNum == 0)
                return new ConfigResult(Constants.ERROR, "批量导入失败，请检查导入数据是否重复");
            return new ConfigResult(Constants.SUCCESS, "批量导入成功" + rowNum + "个，失败" + failNum + "个");
        } catch (Exception e) {
            logger.error(logTxt + "批量导入错误", e);
            return new ConfigResult(Constants.ERROR, "用户批量导入失败，请检查文件内容格式后重新上传");
        }
    }

    /**
     * 按照新模板 批量导入用户信息
     *
     * @param request
     * @param uploadFile
     * @param areaid     省份信息
     * @return
     */
    @ResponseBody
    @RequestMapping("/batchImportUser2")
    public ConfigResult batchImportUser2(
            HttpServletRequest request,
            @RequestParam("uploadFile") MultipartFile uploadFile,
            @RequestParam(required = false, value = "areaid") Long areaid) {
        String logTxt = "【批量导入用户信息】";
        if (areaid == null) {
            // 如果前端没有传递省份id 则默认要导入集团人员 设置默认值 （负值会造成机构页面逻辑混乱）
            areaid = Constants.GROUP_AREAID;
        }
        // 根据areaId获取省份标识 用来和工号一起拼接成用户名
        SysArea area = areaService.selectByPrimaryKey(areaid.intValue());
        String areaCode = area == null ? "JT_" : area.getCode();
        logger.info(logTxt + "省份areaCode= " + areaCode);
        // 用来保存所有读取到的用户信息
        List<Map<String, String>> dataList = new ArrayList<>();
        // 当前操作人信息
        User loginUser = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        Long loginUserId = loginUser.getId();
        // 读取excel文件
        try (Workbook workbook = WorkbookFactory.create(uploadFile.getInputStream())) {
            // 读取第一个sheet表格
            Sheet sheet = workbook.getSheetAt(0);
            // 校验模板是否正确 如果不正确直接返回错误信息
            if (!checkTemplate(sheet)) {
                return new ConfigResult(Constants.ERROR, "请使用正确的模板进行导入");
            }
            // 数据总行数
            int totalRowNum = sheet.getLastRowNum();
            // 跳过第一行标题行
            for (int i = 1; i <= totalRowNum; i++) {
                Row row = sheet.getRow(i);
                if (row == null) continue;
                // 判断如果第一个单元格值为空 则跳过此行不读取
                String c1 = getStringCellValue(row.getCell(0));
                if (StringUtil.isEmpty(c1)) continue;
                // 先把所有数据读取出来 统一进行校验
                Map<String, String> tmp = new HashMap<>();
                tmp.put("rowNum", (i + 1) + "");//行号
                tmp.put("areaCode", areaCode);//省份标识
                tmp.put("groupName", c1);//组织机构名称
                tmp.put("groupType", getStringCellValue(row.getCell(1)));//类型
                tmp.put("roleName", getStringCellValue(row.getCell(2)));//角色
                tmp.put("realName", getStringCellValue(row.getCell(3)));//真实姓名
                tmp.put("account", getStringCellValue(row.getCell(4)));//工号
                tmp.put("mobileNo", getStringCellValue(row.getCell(5)));//手机号
                tmp.put("idCard", getStringCellValue(row.getCell(6)));//身份证
                tmp.put("email", getStringCellValue(row.getCell(7)));//邮箱
                tmp.put("workIp", getStringCellValue(row.getCell(8)));//办公网出口ip
                dataList.add(tmp);
            }
            if (dataList.isEmpty()) {
                return new ConfigResult(Constants.ERROR, "请检查导入的文件内容是否为空");
            }
            // 校验读取到的数据
            StringBuilder errorMsg = new StringBuilder();
            // 一条一条数据写入
            int rowNum = checkExcelContent(dataList, areaid, loginUserId, errorMsg);
            int failNum = dataList.size() - rowNum;
            logger.info(logTxt + "成功批量导入用户" + rowNum + "个," + failNum + "个导入失败");
            if (rowNum == 0) {
                errorMsg.insert(0, "批量导入失败,请重试");
                return new ConfigResult(Constants.ERROR, errorMsg.toString());
            }
            errorMsg.insert(0, "批量导入成功" + rowNum + "个,失败" + failNum + "个");
            return new ConfigResult(Constants.SUCCESS, errorMsg.toString());
        } catch (Exception e) {
            logger.error(logTxt + "批量导入错误", e);
            return new ConfigResult(Constants.ERROR, "用户批量导入失败,请检查文件内容格式后重新上传");
        }
    }

    // 校验导入时使用的模板是否正确
    private boolean checkTemplate(Sheet sheet) {
        // 取一行表头内容校验
        Row row = sheet.getRow(0);
        String[] title = {"部门（班组）", "类型", "角色", "姓名", "工号", "手机号", "身份证号", "邮箱", "办公网出口ip"};
        for (int i = 0; i < title.length; i++) {
            if (!getStringCellValue(row.getCell(i)).equals(title[i])) {
                return false;
            }
        }
        return true;
    }

    // 将从excel中取出的文件信息进行统一校验
    private Integer checkExcelContent(List<Map<String, String>> dataList, Long areaid, Long loginUserId, StringBuilder errorMsg) {
        // 新模板各数据列：组织机构名称、类型、角色、用户名、工号、手机号、身份证、邮箱、办公网出口ip
        // 循环遍历读取到的数据
        int success = 0;
        for (int i = 0; i < dataList.size(); i++) {
            Map<String, String> map = dataList.get(i);
            Integer rowNum = Integer.valueOf(map.get("rowNum"));
            try {
                // 校验组织机构与机构类型
                Long groupId = groupService.insertGroupsOnBatchImportUser(map.get("groupName"), map.get("groupType"), areaid, loginUserId);
                if (groupId.longValue() == Constants.ERROR_GROUP_NAME_EMPTY.longValue()) {
                    errorMsg.append("第" + rowNum + "行机构名称为空;");
                    continue;
                }
                if (groupId.longValue() == Constants.ERROR_GROUP_TYPE_NOT_MATCH.longValue()) {
                    errorMsg.append("第" + rowNum + "行导入的机构名称已经存在，但类型不匹配;");
                    continue;
                }
                // 校验角色
                Long roleId = selectRoleIdByName(map.get("roleName"));
                if (roleId == null) {
                    errorMsg.append("第" + rowNum + "行所选角色不存在;");
                    continue;
                }else if (roleId.equals(-999l)){
                    errorMsg.append("第" + rowNum + "行所选角色已停用;");
                    continue;
                }else{
                    boolean flag=false;
                    SysRoleExample example = new SysRoleExample();
                    // 只检索出启用状态的角色信息
                    example.createCriteria().andStatusEqualTo(1);
                    example.setOrderByClause("name asc");
                    //获取角色当前标识
                    User user = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
                    List<SysRole> sysRoles=new ArrayList<>();
                    if(user.getRolelist().size()==0){//超管
                        sysRoles=roleService.selectByExample(example);
                    }
                    for (SysRole sysRole:user.getRolelist()) {
                        if (sysRole.getCode().lastIndexOf("_") != -1) {//若包含上下级关系
                            for (SysRole role : roleService.selectByExample(example)) {
                                if (role.getCode().indexOf(sysRole.getCode()) == 0){
                                    sysRoles.add(role);
                                }
                            }
                        }else{//含有最高级角色直接返回所有角色
                            sysRoles=roleService.selectByExample(example);
                            break;
                        }
                    }
                    for (SysRole rolesId:sysRoles){
                        if (roleId==rolesId.getId()){
                            flag=true;
                            break;
                        }
                    }
                    if (!flag) {
                        errorMsg.append("您无权限导入第" + rowNum + "行所选角色;");
                        continue;
                    }
                }
                // 校验 用户名 身份证 邮箱
                String account = map.get("account");
                String username = map.get("areaCode") + account;//用户名(省份标识+工号)
                String idcard = map.get("idCard");
                String email = map.get("email");
                String tel=map.get("mobileNo");
                if (checkUsername(username)) {
                    errorMsg.append("第" + rowNum + "行工号已存在;");
                    continue;
                }
                if (idcard.length() > 18) {
                    errorMsg.append("第" + rowNum + "行身份证号长度超过18位;");
                    continue;
                }
                if (!telCheck(tel)) {
                    errorMsg.append("第" + rowNum + "行手机号不合法;");
                    continue;
                }
                if (!checkEmailValid(email)) {
                    errorMsg.append("第" + rowNum + "行Email不合法;");
                    continue;
                }
                if (!checkIdcardValid(idcard)) {
                    errorMsg.append("第" + rowNum + "行身份证号不合法;");
                    continue;
                }

                // 保存用户信息
                User user = new User();
                user.setGroupid(groupId);// 设置机构id
                List<Long> roleIdList = new ArrayList<>();
                roleIdList.add(roleId);
                user.setRoleidlist(roleIdList);// 设置角色id
                user.setUsername(username);//用户名
                user.setRealname(map.get("realName"));//真实姓名
                user.setAccount(account);//工号
                user.setMobileno(tel);//手机号
                user.setIdcard(idcard);//身份证
                user.setEmail(email);//邮箱
                user.setWorkip(map.get("workIp"));//办公网出口ip
                // 其他信息
                user.setPassword(getInitPassword());
                user.setCreatetime(new Date());
                user.setCreateuserid(loginUserId);
                userService.insert(user);
                success++;//成功数量加1
            } catch (Exception e) {
                logger.error("校验第" + rowNum + "行组织机构数据过程中发生错误", e);
                errorMsg.append("第" + rowNum + "行数据写入失败，请重试;");
            }
        }
        return success;
    }

    // 根据角色名称获取角色id
    private Long selectRoleIdByName(String roleName) {
        if (StringUtil.isNotEmpty(roleName)) {
            SysRoleExample example = new SysRoleExample();
            example.createCriteria().andNameEqualTo(roleName);
            List<SysRole> roleList = roleService.selectByExample(example);
            if (roleList.get(0).getStatus()==0) {//判断角色是否停用
                Long fail=-999L;
                return fail;
            }
            if (!roleList.isEmpty()) {
                return roleList.get(0).getId();
            }
        }
        return null;
    }

    // 校验用户名 邮件 身份证是否存在 存在返回true  不存在返回false
    private boolean checkUsername(String username) {
        // 校验用户名/email/idcard已存在 则跳过该用户
        UserExample example = new UserExample();
        example.createCriteria().andUsernameEqualTo(username);
        return userService.countByExample(example) > 0;
    }

    // 校验用户名 邮件 身份证是否存在 存在返回true  不存在返回false
    private boolean checkIdcard(String idcard) {
        // 校验用户名idcard已存在 则跳过该用户
        UserExample example = new UserExample();
        example.createCriteria().andIdcardEqualTo(idcard);
        return userService.countByExample(example) > 0;
    }

    // 校验用户名 邮件 身份证是否存在 存在返回true  不存在返回false
    private boolean checkEmail(String email) {
        // 校验用户名email已存在 则跳过该用户
        UserExample example = new UserExample();
        example.createCriteria().andEmailEqualTo(email);
        return userService.countByExample(example) > 0;
    }

    /**
     * 校验手机号合法性
     *
     */
    private boolean telCheck(String tel){
        if (tel.length() != 11) {
            return false;
        }
        String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(tel);
        return m.matches();
    }

    /**
     * 校验email合法性
     *
     */
    private boolean checkEmailValid(String email) {
        String regex="^[A-Za-z\\d]+([-_.][A-Za-z\\d]+)*@([A-Za-z\\d]+[-.])+[A-Za-z\\d]{2,4}$";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(email);
        return m.matches();
    }

    /**
     * 校验身份证号合法性
     *
     */
    private boolean checkIdcardValid(String idcard) {
        String regex="^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$|^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(idcard);
        return m.matches();
    }
    // 对单元格的值统一处理 返回字符
    private String getStringCellValue(Cell cell) {
        if (cell == null) return "";
        if (CellType.NUMERIC == cell.getCellType()) {
            cell.setCellType(CellType.STRING);
        }
        return cell.getStringCellValue().trim();
    }

    /**
     * 导出基础信息到excel表
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/exportBase", method = RequestMethod.GET)
    public void exportBase(HttpServletRequest request, HttpServletResponse response) {
        logger.info("导出用户基础信息信息");
        // 生成的excel的列名
        String[] columnNames = {"省份", "部门(班组)", "类型", "角色", "姓名", "工号", "登录账号", "办公网出口ip"};
        // 对应的实体类的属性名
        String[] filedNames = {"area", "groupname", "grouptype", "rolename", "realname", "account", "username", "workip"};
        // 调用共用方法 生成excel下载
        export(request, response, columnNames, filedNames);
    }

    /**
     * 导出用户详细信息到excel表
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/exportDetail", method = RequestMethod.GET)
    public void exportDetail(HttpServletRequest request, HttpServletResponse response) {
        logger.info("导出用户信息");
        // 生成的excel的列名
        String[] columnNames = {"省份", "部门(班组)", "类型", "登录账号", "角色", "姓名", "工号", "手机号", "身份证", "邮箱", "办公网出口ip"};
        // 对应的实体类的属性名
        String[] filedNames = {"area", "groupname", "grouptype", "username", "rolename", "realname", "account", "mobileno", "idcard", "email", "workip"};
        export(request, response, columnNames, filedNames);
    }

    // 共用的导出下载用户信息
    private void export(HttpServletRequest request, HttpServletResponse response, String[] columnNames, String[] filedNames) {
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        // 获取查询条件：选中了哪几条数据
        String userIdList = request.getParameter("userIdList");
        // 如果选中的userId不为空 则只导出对应的用户信息
        if (StringUtil.isNotEmpty(userIdList)) {
            String[] array = userIdList.split(",");
            List<Long> idList = new ArrayList<>();
            for (String userId : array) {
                try {
                    idList.add(Long.valueOf(userId));
                } catch (NumberFormatException e) {
                    // 格式化错误的不用管
                }
            }
            if (!userIdList.isEmpty()) {
                criteria.andIdIn(idList);
            }
        }
        // 其他查询条件
        String areaId = request.getParameter("areaId");   //省份id
        String groupId = request.getParameter("groupId");   //组织机构id
        String account = request.getParameter("account");   //工号
        String userName = request.getParameter("userName"); //用户名
        String realName = request.getParameter("realName"); //真实姓名
        String isDelete = request.getParameter("isDelete"); //状态
        String sortName = request.getParameter("sortName"); //排序名称
        String sortOrder = request.getParameter("sortOrder"); //排序方式
        if (StringUtil.isEmpty(groupId)) {
            // 当groupId为空 判断areaid 获取当前登录用户允许访问的组织机构范围
            List<Long> subGroupIdList = userService.getAllSubGroupId(areaId);
            if (!subGroupIdList.isEmpty()) {
                criteria.andGroupidIn(subGroupIdList);
            }
        }
        if (StringUtil.isNotEmpty(groupId) && groupId.matches("\\d*")) {
            criteria.andGroupidEqualTo(Long.valueOf(groupId));
        }
        if (StringUtil.isNotEmpty(account)) {
            criteria.andAccountLike("%" + account + "%");
        }
        if (StringUtil.isNotEmpty(userName)) {
            criteria.andUsernameLike("%" + userName + "%");
        }
        if (StringUtil.isNotEmpty(realName)) {
            criteria.andRealnameLike("%" + realName + "%");
        }
        if (StringUtil.isNotEmpty(isDelete)) {
            String[] isDeleteArray = isDelete.split(",");
            List<Integer> isDeleteList = new ArrayList<>();
            for (String s : isDeleteArray) {
                try {
                    isDeleteList.add(Integer.valueOf(s));
                } catch (NumberFormatException e) {
                }
            }
            criteria.andIsdeleteIn(isDeleteList);
        }
        example.setOrderByClause(sortName + " " + sortOrder);
        List<Map<String, Object>> userList = userService.selectUserDataToExport(example);
        HSSFWorkbook hwb = fillDataIntoExcel(userList, columnNames, filedNames);
        try {
            //输出文件名
            String fileName = "用户信息表";
            // 创建文件输出流，准备输出电子表格
            response.reset();
            response.setContentType("application/msexcel"); // 定义输出类型
            response.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes("GBK"), StandardCharsets.ISO_8859_1) + ".xls"); // 设定输出文件头
            OutputStream os = response.getOutputStream();
            hwb.write(os);
            os.close();
        } catch (IOException e) {
            logger.error("用户信息导出失败", e);
        }
    }

    /**
     * 填充数据到excel中
     *
     * @param userList    数据
     * @param columnNames 生成的excel的列名
     * @param filedNames  对应的实体类的属性名
     * @return
     */
    private HSSFWorkbook fillDataIntoExcel(List<Map<String, Object>> userList, String[] columnNames, String[] filedNames) {
        // 创建excel文档对象
        HSSFWorkbook hwb = new HSSFWorkbook();
        // 创建sheet对象 设置名称
        HSSFSheet sheet = hwb.createSheet("用户信息表");
        // 设置单元格样式
        HSSFCellStyle cellStyle = hwb.createCellStyle();
//        cellStyle.setAlignment(HSSFCellStyle.ALIGN_LEFT);
//        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setBorderBottom(BorderStyle.THIN);
        // 创建标题行
        HSSFRow firstRow = sheet.createRow(0);
        for (int i = 0; i < columnNames.length; i++) {
            HSSFCell c = firstRow.createCell(i);
            c.setCellValue(columnNames[i]);
            c.setCellStyle(cellStyle);
        }
        // 循环写入用户信息
        for (int i = 0; i < userList.size(); i++) {
            HSSFRow row = sheet.createRow(i + 1);
            Map<String, Object> userInfo = userList.get(i);
            for (int j = 0; j < filedNames.length; j++) {
                HSSFCell cell = row.createCell(j);
                cell.setCellValue((String) userInfo.get(filedNames[j]));
                cell.setCellStyle(cellStyle);
            }
        }
        return hwb;
    }

    /**
     * 根据省份id、机构id查询该机构下所有客服的工号
     * 质检人员只能查询自己管辖的坐席组的人员信息
     * 坐席人员：组长可以查看自己组的，组员只能看自己的
     * 运营管理、超管、集团人员：可以看所有的
     *
     * @param seatGroupId 坐席班组id
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/selectAccountByAreaGroupId", method = RequestMethod.POST)
    public List<Map<String, Object>> selectAccountByAreaGroupId(Long areaId, Long seatGroupId) {
        logger.info("获取某班组下所有客服人员的工号【areaId=" + areaId + ", seatGroupId=" + seatGroupId + "】");
        Session session = SecurityUtils.getSubject().getSession();
        User user = (User) session.getAttribute(Constants.SESSION_USER_INFO);
        // 先确定要查询哪些坐席机构 然后根据机构查询坐席信息
        SysGroupExample groupExample = new SysGroupExample();
        SysGroupExample.Criteria groupCriteria = groupExample.createCriteria();
        if (areaId == null) {
            // 判断登录人有没有所属省份
            SysArea area = (SysArea) session.getAttribute("areaInfo");
            if (area != null) {
                // 说明为某个省份的人员 只查询该省的
                groupCriteria.andAreaidEqualTo(area.getId().longValue());
            }
        } else {
            groupCriteria.andAreaidEqualTo(areaId);
        }
        if (seatGroupId == null) {
            // 判断登录人身份 如果是质检 只查询自己管辖的坐席组 如果是运营管理 则所有坐席组
            int userIdentity = (int) session.getAttribute("userIdentity");
            if (userIdentity == 1) {
                // 质检人员 查询出来质检管辖的坐席组
                List<SysGroup> groupList = groupService.selectSeatGroupByQcGroupId(user.getGroupid(), user.getId());
                List<Long> groupIdList = new ArrayList<>();
                for (SysGroup group : groupList) {
                    groupIdList.add(group.getId());
                }
                if (groupIdList.isEmpty()) {
                    // 如果没有管辖的坐席组 则不允许查询出信息
                    groupIdList.add(-404L);
                }
                groupCriteria.andIdIn(groupIdList);
            } else if (userIdentity == 2) {
                // 查询所有坐席组：type=0的机构
                groupCriteria.andTypeEqualTo(0);
            } else {
                // 坐席人员
                List<SysRole> rolelist = user.getRolelist();
                // 标记是否为组长角色 组长可以查询整个组人信息 组员只能查询自己
                boolean isTL = false;
                for (SysRole sysRole : rolelist) {
                    if (sysRole.getParentroleid() != null) {
                        // 查询所在组所有人员信息
                        groupCriteria.andIdEqualTo(user.getGroupid());
                        isTL = true;
                    }
                }
                if (!isTL) {
                    // 普通坐席人员 只返回自己的信息
                    List<Map<String, Object>> result = new ArrayList<>();
                    Map<String, Object> tmp = new HashMap<>();
                    tmp.put("id", user.getId());
                    tmp.put("userName", user.getUsername());
                    tmp.put("realName", user.getRealname());
                    tmp.put("account", user.getAccount());
                    result.add(tmp);
                    return result;
                }
            }
        } else {
            groupCriteria.andIdEqualTo(seatGroupId);
        }
        // 查询出来所有符合条件的机构
        List<SysGroup> groupList = groupService.selectByExample(groupExample);
        List<Long> groupIdList = new ArrayList<>();
        for (SysGroup group : groupList) {
            groupIdList.add(group.getId());
        }
        if (groupIdList.isEmpty()) {
            // 如果没有机构 则不允许查询出用户信息 同时避免sql异常
            groupIdList.add(-404L);
        }
        // 根据机构再去查询用户信息
        UserExample example = new UserExample();
        example.createCriteria().andGroupidIn(groupIdList);
        List<User> userList = userService.selectByExample(example);
        // 普通坐席人员 只返回自己的信息
        List<Map<String, Object>> result = new ArrayList<>();
        for (User u : userList) {
            Map<String, Object> tmp = new HashMap<>();
            tmp.put("id", u.getId());
            tmp.put("userName", u.getUsername());
            tmp.put("realName", u.getRealname());
            tmp.put("account", u.getAccount());
            result.add(tmp);
        }
        return result;
    }

    /**
     * 质检员获取管辖的坐席组 坐席人员获取自己的坐席组信息
     *
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/selectManagedSeatGroup", method = RequestMethod.GET)
    public List<SysGroup> selectManagedSeatGroup(HttpServletRequest request) {
        Session session = SecurityUtils.getSubject().getSession();
        User loginUser = (User) session.getAttribute(Constants.SESSION_USER_INFO);
        // 获取用户身份 坐席0，质检员1  其他2）
        Integer userType = (Integer) session.getAttribute("userIdentity");
        if (0 == userType) {
            // 如果是坐席 则返回自己所属部门信息
            SysGroup group = loginUser.getGroup();
            List<SysGroup> list = new ArrayList<>();
            list.add(group);
            return list;
        } else if (1 == userType) {
            // 如果是质检员 则查询出自己所管辖的坐席组
            return userService.selectManagedSeatGroupByUserId(loginUser.getId());
        } else {
            SysArea area = (SysArea) session.getAttribute("areaInfo");
            // 判断是不是集团人员 各自查询各自省份的坐席组
            SysGroupExample example = new SysGroupExample();
            SysGroupExample.Criteria criteria = example.createCriteria();
            if (area == null) {
                criteria.andAreaidEqualTo(Constants.GROUP_AREAID).andTypeEqualTo(0);
            } else {
                criteria.andAreaidEqualTo(area.getId().longValue()).andTypeEqualTo(0);// type=0为坐席
            }
            return groupService.selectByExample(example);
        }
    }

    /**
     * 质检员获取管辖的坐席人员 坐席人员获取自己的信息
     *
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/selectManagedSeat", method = RequestMethod.GET)
    public List<Map<String, Object>> selectManagedSeat(HttpServletRequest request) {
        Session session = SecurityUtils.getSubject().getSession();
        // 获取用户身份 坐席0，质检员1  其他2）
        Integer userType = (Integer) session.getAttribute("userIdentity");
        if (0 == userType || 1 == userType) {
            // 如果是质检或者坐席角色
            List<User> userList = selectDataPermission();
            List<Map<String, Object>> seatInfo = new ArrayList<>();
            if (!userList.isEmpty()) {
                for (User user : userList) {
                    Map<String, Object> tmp = new HashMap<>();
                    tmp.put("account", user.getAccount());
                    tmp.put("realName", user.getRealname());
                    seatInfo.add(tmp);
                }
            }
            return seatInfo;
        } else {
            // 超管 查询所有坐席信息
            return userService.selectAllSeat();
        }
    }

    /**
     * 获取当前登录用户密码设置时间
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/passSetTime", method = RequestMethod.GET)
    public Date selectPassSetTime() {
        // 更新session中用户信息 然后直接取出用户中的密码设置时间
        updateUserInfo();
        User user = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        return user.getPswsettime();
    }

    /**
     * 根据userId获取其组员userId（含自己）
     * 组长组员必须属于同一组织机构
     *
     * @param userId 用户id
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/selectMemberIdByLeaderId", method = GET)
    public List<Long> selectMemberIdByLeaderId(@RequestParam(value = "userId") Long userId) {
        String logTxt = "【根据userId获取其组员userId（含自己）】";
        logger.info(logTxt + "userId=" + userId);

        List<Long> userIdList = new ArrayList<>();

        // TODO 需根据需求判断null、超级管理员、集团用户
        if (userId == null) {
            System.err.println("userId为空");
        } else if (userId == 1L) {
            userIdList.add(1L);
        } else {
            userIdList = userService.selectMemberIdByLeaderId(userId);

            logger.info(logTxt + "共计查询到" + userIdList.size() + "个用户id");
        }

        return userIdList;
    }

    /**
     * @param userId 用户id
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/selectUserListById", method = GET)
    public List<User> selectUserListById(@RequestParam(value = "userId") List userId) {
        String logTxt = "【根据userId获取id，工号，姓名】";
        logger.info(logTxt + "userId=" + userId);
        List<User> userIdList=new ArrayList<>();
        if (userId.size()==0) {
            System.err.println("userId为空");
            return userIdList;
        }
        userIdList = userService.selectUserListById(userId);
        logger.info(logTxt + "共计查询到" + userIdList.size() + "个用户id");
        return userIdList;
    }
}
